home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 331_01 / swap.c < prev    next >
Text File  |  1990-06-12  |  10KB  |  357 lines

  1. /*
  2. HEADER:         CUG199.09;
  3. TITLE:          GED (nee QED) screen editor -- part 9;
  4. DATE:           10/10/86;
  5.  
  6. DESCRIPTION:   "Virtual memory manager for GED editor. Eg. swapout,
  7.                 pageout.";
  8. KEYWORDS:       text storage, memory management, virtual storage, paging;
  9. SYSTEM:         MS-DOS;
  10. FILENAME:       GED9.C;
  11. AUTHORS:        G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
  12. COMPILERS:      DeSmet C;
  13. */
  14.  
  15. /*
  16.      e/qed/ged  screen editor
  17.  
  18.     (C) G. Nigel Gilbert, MICROLOGY, 1981
  19.            August-December 1981
  20.  
  21.     Modified:  Aug-Dec   1984:   BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
  22.                March     1985:   BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
  23.                May       1986:   converted to ged - Mel Tearle
  24.  
  25.     FILE:      ged9.c
  26.  
  27.     FUNCTIONS: initvm, freememslot, swapout, writepage,
  28.                swappin, readpage, fatalerror
  29.  
  30.     PURPOSE:   manages virtual memory
  31.  
  32. */
  33.  
  34. #include <stdio.h>
  35. #include "ged.h"
  36.  
  37. int allo;
  38.  
  39. /* Initialize virtual memory system.  There are MAXSLOTS pages.  The data in a given
  40.    page may be either in RAM or in a temporary disc file.  The most recently
  41.    used data is kept in RAM.  There are up to RAMSLOTS of pages in RAM.
  42.  
  43.    If virtslot[page] is positive then the value is the slot number in RAM
  44.    which contains the text for that page.  If negative then the disc slot
  45.    number is -(virtslot[page] + 1).
  46.  
  47.    Selective use is made of 32-bit pointers.  Most of the program uses 16-bit
  48.    pointers and would be difficult and inefficient to convert to a large
  49.    data model.  Pointer arithmetic on far pointers cannot cross a 64k boundary.
  50.    Huge pointer calculations can cross these boundaries.  The use of far and
  51.    huge pointers is controlled by the preprocessor directives in ged.h.
  52.  
  53.    If the page size is evenly divisible into 64 k then a page will never
  54.    span a 64 k boundary and far pointers can be used in time critical functions.
  55.    The far pointer arithmetic is significantly faster for far pointers and
  56.    they are used in this version.  There are also places where huge
  57.    pointer arithmetic must be used in order to obtain correct carry
  58.    propogation.
  59.  
  60.  */
  61. initvm()
  62. {
  63.     int   slot;
  64.     unsigned int size;
  65.     static unsigned long int lsize;
  66.     static char  HUGE * hptr = 0L;
  67.     char  HUGE * cdecl hptr1;
  68.     int i;
  69.     long int ll;
  70.     char  *malloc();
  71.     char *ptr;
  72.     char HUGE * malloc2();
  73.     char buf[40];
  74.     if (sizeof(*tp) != sizeof(long))
  75.         cerr(92);  /* see comments in deltp() */
  76.  
  77. /* fullmem set by -M load time option */
  78.     if (hptr == 0L) {
  79.         lsize =  (long) fullmem*1024L;
  80.         hptr = malloc2(&lsize);  /* adjusts lsize downward */
  81.     }
  82.     hptr1 = hptr;
  83.     slotsinmem = lsize/PAGESIZE;
  84.  
  85.     if ( slotsinmem < 3 )  {
  86.         error1( "Can't allocate enough memory" );
  87.         xit();
  88.     }
  89.     allo = lsize/1024L;
  90.     for (slot = 0;  slot < slotsinmem;  slot++) {
  91.         usage[slot] = 0;
  92.         auxloc[slot] = 0;
  93.         slotaddr[slot] = hptr1;
  94.         hptr1 += PAGESIZE;
  95.     }
  96.     for (i = 0;  i < MAXSLOTS;  i++) {
  97.         virtslot[i] = 0;
  98.         dskslots[i] = 0;
  99.     }
  100.  
  101.     clock = 1;
  102.  
  103. /* reserve slot 0 for an array of tp structures.  Additional slots
  104.  * will be taken later for tp if needed.
  105.  */
  106.     tp = (struct addr HUGE *)slotaddr[0];
  107.     tpslots  = 1;
  108.     usage[tpslots-1] = -1;
  109.  
  110. /* assign first page for line injection. */
  111.     newpage = 0;
  112.     virtslot[newpage] = freememslot();
  113.     allocp = 0;
  114.     usage[virtslot[newpage]] = MAXINT;
  115.  
  116. /* paging file not yet created */
  117.     pagefd = NOFILE;
  118.     return;
  119. }
  120.  
  121.  
  122. /* Returns the number of a free memory slot, possibly by swapping out
  123.    the least recently used page currently in memory.  If that page is
  124.    already on disc then the RAM slot is immediately reused.
  125.    On the initial read, text is stored starting at the top of allocated
  126.    memory and working downward.  The tp array works upward from low memory.
  127.    The portion used by tp must be contiguous.  newpage is not swaped out.
  128.  */
  129. int freememslot()
  130. {
  131.     int  use, u;
  132.     int  i, slot, nclk;
  133.  
  134.     nclk = 1;
  135.     use = MAXINT;
  136.     slot = slotsinmem-1;
  137.     for ( i = slotsinmem-1; (use != 0) && (i >= tpslots); i-- ) {
  138.         if ( ( u = usage[i] ) < use )  {
  139.             use  = u;
  140.             slot = i;
  141.         }
  142.     }
  143.     if ( use > 0 ) {
  144.         swapout( slot );  /* no free slots. make one */
  145.     }
  146.     auxloc[slot] = 0;  /* RAM slot has no disc association */
  147.     if (!goteof)
  148.         usage[slot] = clock++;
  149.     return  slot;
  150. }
  151.  
  152.  
  153. /* swaps page currently in memory at 'slot' to disk,
  154.  * updating virtslot to show new location
  155.  */
  156. swapout(slot)
  157. int  slot;
  158. {
  159.     int  pg;
  160.  
  161. /* find page number for ram data at 'slot' */
  162.     for ( pg = 0; (virtslot[pg] != slot) && (pg < MAXSLOTS); pg++ )
  163.         ;
  164.     if(pg==MAXSLOTS)
  165.         cerr(90);   /* memory is probably clobbered */
  166.  
  167.     if (auxloc[slot] == 0) {
  168.         virtslot[pg] =  -writepage( slot ) - 1;  /* update virtslot with disk slot written to */
  169.     }
  170.     else {
  171.         virtslot[pg] = auxloc[slot];  /* page already exists on disc */
  172.         auxloc[slot] = 0;  /* RAM slot will lose its disc association with this record */
  173.     }
  174.     usage[slot] = 0;  /* the ram slot is free */
  175.     return;
  176. }
  177.  
  178.  
  179. /* Writes page currently in memory at 'slot' to disk.
  180.  * Returns disk slot where written.  Locations near the beginning
  181.  * of the file are used when available to miminize total file size.
  182.  */
  183. writepage(slot)
  184. int slot;
  185. {
  186.     int i;
  187.     unsigned loc;
  188.     long int sekbytes;
  189.     long int lseek1();
  190.  
  191.     long int dbuf[PAGESIZE/sizeof(long)];
  192.     long int *pt1;
  193.     long int FAR *pt2;
  194.  
  195.  
  196.     if ( pagefd == NOFILE )  {       /* haven't opened paging file yet */
  197.  
  198.         if ( (pagefd = creatb(pagingfile)) == FAIL )
  199.             fatalerror( " Can't create a buffer file" );
  200.         for ( loc = 0; loc < MAXSLOTS; loc++ )
  201.             dskslots[loc] = 0;
  202.     }
  203.  
  204.     for ( loc = 0; dskslots[loc] != 0; loc++ )   /* find a free slot */
  205.         ;
  206.     if (loc >= MAXSLOTS)
  207.         cerr(93);         /* table corrupt */
  208.     sekbytes = (long) loc*PAGESIZE;
  209.  
  210.     if ( lseek1( pagefd, sekbytes) == -1L )
  211.         fatalerror(" Bad seek in writing buffer ");
  212.  
  213. /* move far data to near data */
  214.     pt2 = (long int FAR *) slotaddr[slot];
  215.     pt1 = &dbuf[0];
  216.     for (i = 1; i <= PAGESIZE/sizeof(long); i++)
  217.         *pt1++ = *pt2++;
  218.  
  219.     if ( write( pagefd, dbuf, PAGESIZE ) == FAIL )
  220.         fatalerror(" Can't write to buffer - disk full " );
  221.     dskslots[loc] = 1;
  222.     usage[slot]   = 0;
  223.     return  loc;
  224. }
  225.  
  226.  
  227. /* get 'page', currently on disk,
  228.  * into memory and return slot where placed
  229.  * the disc location is saved in auxloc in case the page needs to be
  230.  * rolled out again without change.
  231.  *
  232.  * The priority is set to 1 when read.  If read for a global string search
  233.  * the priority stays at the lowest priority and the same memory slot will
  234.  * be used for the next page.  The established page priority is therefore
  235.  * mostly unaffected by global searches.  If loaded for gettext() the
  236.  * priority will immediately be raised to 'clock' and the page will
  237.  * usually stay resident for a long time.
  238.  */
  239. swappin(page)
  240. int  page;
  241. {
  242.     int  slot, dslot;
  243. int i;
  244.     if(virtslot[page] >= 0)
  245.         cerr(91);          /* table corrupt */
  246.     slot = freememslot();
  247.     readpage( slot, -1 -virtslot[page] );
  248.     usage[slot] = 1;
  249.     auxloc[slot] = virtslot[page]; /* remember where it came from */
  250.     virtslot[page] = slot;
  251.     return slot;
  252. }
  253.  
  254.  
  255. /* read a page from disk into
  256.  * memory at 'memsl'
  257.  */
  258. readpage(memsl,dskslot)
  259. int memsl, dskslot;
  260. {
  261.     long sekbytes;
  262.     int i;
  263.     long int *pt1;
  264.     long int FAR *pt2;
  265.     long int dbuf[PAGESIZE/sizeof(long)];
  266.     char buf[80];
  267.     long int lseek1();
  268.  
  269.     sekbytes = (long) dskslot*PAGESIZE;
  270.     if ( lseek1( pagefd, sekbytes ) == -1L )
  271.         fatalerror(" Bad seek in reading buffer ");
  272.     i=read( pagefd, dbuf, PAGESIZE );
  273.     if ( i != PAGESIZE )
  274.         fatalerror(" Can't read disc